package com.shtb.wisdom.videotaker

import android.content.Context
import android.graphics.PixelFormat
import android.media.AudioManager
import android.media.MediaPlayer
import android.media.MediaPlayer.*
import android.net.Uri
import android.os.Build
import android.os.Handler
import android.os.Message
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.SurfaceHolder
import android.view.SurfaceView
import java.io.IOException

class SurfaceVideoView : SurfaceView, KeyEvent.Callback, SurfaceHolder.Callback {
    private var mOnCompletionListener: OnCompletionListener? = null
    private var mOnPreparedListener: OnPreparedListener? = null
    private var mOnErrorListener: OnErrorListener? = null
    private var mOnSeekCompleteListener: OnSeekCompleteListener? = null
    private var mOnInfoListener: OnInfoListener? = null
    private var mOnVideoSizeChangedListener: OnVideoSizeChangedListener? = null
    private var mOnPlayStateListener: OnPlayStateListener? = null
    private var mMediaPlayer: MediaPlayer? = null
    var surfaceHolder: SurfaceHolder? = null
        private set
    private var mCurrentState = STATE_IDLE
    private var mTargetState = STATE_IDLE
    var videoWidth = 0
        private set
    var videoHeight = 0
        private set

    //	private int mSurfaceWidth;
    //	private int mSurfaceHeight;
    private var mSystemVolumn = -1f
    var duration = 0
        private set
    private var mUri: Uri? = null

    //	SurfaceTextureAvailable
    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyle: Int
    ) : super(context, attrs, defStyle) {
        initVideoView()
    }

    constructor(context: Context?) : super(context) {
        initVideoView()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(
        context,
        attrs
    ) {
        initVideoView()
    }

    protected fun initVideoView() {
        //		mTryCount = 0;
        videoWidth = 0
        videoHeight = 0
        holder.setFormat(PixelFormat.RGBA_8888) // PixelFormat.RGB_565
        holder.addCallback(this)
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)
        }
        isFocusable = true
        isFocusableInTouchMode = true
        requestFocus()
        mCurrentState = STATE_IDLE
        mTargetState = STATE_IDLE
    }

    fun setOnInfoListener(l: OnInfoListener?) {
        mOnInfoListener = l
    }

    fun setOnVideoSizeChangedListener(l: OnVideoSizeChangedListener?) {
        mOnVideoSizeChangedListener = l
    }

    fun setOnPreparedListener(l: OnPreparedListener?) {
        mOnPreparedListener = l
    }

    fun setOnErrorListener(l: OnErrorListener?) {
        mOnErrorListener = l
    }

    fun setOnPlayStateListener(l: OnPlayStateListener?) {
        mOnPlayStateListener = l
    }

    fun setOnSeekCompleteListener(l: OnSeekCompleteListener?) {
        mOnSeekCompleteListener = l
    }

    interface OnPlayStateListener {
        fun onStateChanged(isPlaying: Boolean)
    }

    fun setOnCompletionListener(l: OnCompletionListener?) {
        mOnCompletionListener = l
    }

    fun setVideoPath(path: String?) {
        if (path != null && !path.isEmpty()) {
            mTargetState = STATE_PREPARED
            openVideo(Uri.parse(path))
        }
    }

    fun reOpen() {
        mTargetState = STATE_PREPARED
        openVideo(mUri)
    }

    /** 重试  */
    private fun tryAgain(e: Exception) {
        mCurrentState = STATE_ERROR
        openVideo(mUri)
    }

    fun start() {
        mTargetState = STATE_PLAYING
        //可用状态{Prepared, Started, Paused, PlaybackCompleted}
        if (mMediaPlayer != null && (mCurrentState == STATE_PREPARED || mCurrentState == STATE_PAUSED || mCurrentState == STATE_PLAYING || mCurrentState == STATE_PLAYBACK_COMPLETED)) {
            try {
                if (!isPlaying) mMediaPlayer!!.start()
                mCurrentState = STATE_PLAYING
                if (mOnPlayStateListener != null) mOnPlayStateListener!!.onStateChanged(true)
            } catch (e: IllegalStateException) {
                tryAgain(e)
            } catch (e: Exception) {
                tryAgain(e)
            }
        }
    }

    fun pause() {
        mTargetState = STATE_PAUSED
        //可用状态{Started, Paused}
        if (mMediaPlayer != null && mCurrentState == STATE_PLAYING) {
            try {
                mMediaPlayer!!.pause()
                mCurrentState = STATE_PAUSED
                if (mOnPlayStateListener != null) mOnPlayStateListener!!.onStateChanged(false)
            } catch (e: IllegalStateException) {
                tryAgain(e)
            } catch (e: Exception) {
                tryAgain(e)
            }
        }
    }

    /** 处理音量键  */
    fun dispatchKeyEvent(
        context: Context?,
        event: KeyEvent
    ) {
        when (event.keyCode) {
            KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP -> setVolume(
                getSystemVolumn(context)
            )
        }
    }

    fun setVolume(volume: Float) {
        //可用状态{Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted}
        if (mMediaPlayer != null && (mCurrentState == STATE_PREPARED || mCurrentState == STATE_PLAYING || mCurrentState == STATE_PAUSED || mCurrentState == STATE_PLAYBACK_COMPLETED)) {
            try {
                mMediaPlayer!!.setVolume(volume, volume)
            } catch (e: Exception) {
            }
        }
    }

    fun setLooping(looping: Boolean) {
        //可用状态{Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted}
        if (mMediaPlayer != null && (mCurrentState == STATE_PREPARED || mCurrentState == STATE_PLAYING || mCurrentState == STATE_PAUSED || mCurrentState == STATE_PLAYBACK_COMPLETED)) {
            try {
                mMediaPlayer!!.isLooping = looping
            } catch (e: Exception) {
            }
        }
    }

    fun seekTo(msec: Int) {
        //可用状态{Prepared, Started, Paused, PlaybackCompleted}
        var msec = msec
        if (mMediaPlayer != null && (mCurrentState == STATE_PREPARED || mCurrentState == STATE_PLAYING || mCurrentState == STATE_PAUSED || mCurrentState == STATE_PLAYBACK_COMPLETED)) {
            try {
                if (msec < 0) msec = 0
                mMediaPlayer!!.seekTo(msec)
            } catch (e: IllegalStateException) {
            } catch (e: Exception) {
            }
        }
    }//可用状态{Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}

    /** 获取当前播放位置  */
    val currentPosition: Int
        get() {
            var position = 0
            //可用状态{Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}
            if (mMediaPlayer != null) {
                when (mCurrentState) {
                    STATE_PLAYBACK_COMPLETED -> position = duration
                    STATE_PLAYING, STATE_PAUSED -> try {
                        position = mMediaPlayer!!.currentPosition
                    } catch (e: IllegalStateException) {
                    } catch (e: Exception) {
                    }
                }
            }
            return position
        }

    //可用状态{Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}
    val isPlaying: Boolean
        get() {
            //可用状态{Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}
            if (mMediaPlayer != null && mCurrentState == STATE_PLAYING) {
                try {
                    return mMediaPlayer!!.isPlaying
                } catch (e: IllegalStateException) {
                } catch (e: Exception) {
                }
            }
            return false
        }

    /** 调用release方法以后MediaPlayer无法再恢复使用  */
    fun release() {
        mTargetState = STATE_RELEASED
        mCurrentState = STATE_RELEASED
        if (mMediaPlayer != null) {
            try {
                mMediaPlayer!!.release()
            } catch (e: IllegalStateException) {
            } catch (e: Exception) {
            }
            mMediaPlayer = null
        }
    }

    fun openVideo(uri: Uri?) {
        if (uri == null || surfaceHolder == null || context == null) {
            // not ready for playback just yet, will try again later
            if (surfaceHolder == null && uri != null) {
                mUri = uri
            }
            return
        }
        mUri = uri
        duration = 0

        //Idle 状态：当使用new()方法创建一个MediaPlayer对象或者调用了其reset()方法时，该MediaPlayer对象处于idle状态。
        //End 状态：通过release()方法可以进入End状态，只要MediaPlayer对象不再被使用，就应当尽快将其通过release()方法释放掉
        //Initialized 状态：这个状态比较简单，MediaPlayer调用setDataSource()方法就进入Initialized状态，表示此时要播放的文件已经设置好了。
        //Prepared 状态：初始化完成之后还需要通过调用prepare()或prepareAsync()方法，这两个方法一个是同步的一个是异步的，只有进入Prepared状态，才表明MediaPlayer到目前为止都没有错误，可以进行文件播放。
        var exception: Exception? = null
        try {
            if (mMediaPlayer == null) {
                mMediaPlayer = MediaPlayer()
                mMediaPlayer!!.setOnPreparedListener(mPreparedListener)
                mMediaPlayer!!.setOnCompletionListener(mCompletionListener)
                mMediaPlayer!!.setOnErrorListener(mErrorListener)
                mMediaPlayer!!.setOnVideoSizeChangedListener(mVideoSizeChangedListener)
                mMediaPlayer!!.setAudioStreamType(AudioManager.STREAM_MUSIC)
                mMediaPlayer!!.setOnSeekCompleteListener(mSeekCompleteListener)
                mMediaPlayer!!.setOnInfoListener(mInfoListener)
                mSystemVolumn = getSystemVolumn(context)
                mMediaPlayer!!.setVolume(mSystemVolumn, mSystemVolumn)
                mMediaPlayer!!.setDisplay(surfaceHolder)
            } else {
                mMediaPlayer!!.reset()
            }
            mMediaPlayer!!.setDataSource(context, uri)

            //			if (mLooping)
            //				mMediaPlayer.setLooping(true);//循环播放
            mMediaPlayer!!.prepareAsync()
            // we don't set the target state here either, but preserve the
            // target state that was there before.
            mCurrentState = STATE_PREPARING
        } catch (ex: IOException) {
            exception = ex
        } catch (ex: IllegalArgumentException) {
            exception = ex
        } catch (ex: Exception) {
            exception = ex
        }
        if (exception != null) {
            mCurrentState = STATE_ERROR
            mErrorListener?.onError(
                mMediaPlayer,
                MEDIA_ERROR_UNKNOWN,
                0
            )
        }
    }

    private val mCompletionListener = OnCompletionListener { mp ->
        mCurrentState = STATE_PLAYBACK_COMPLETED
        //			mTargetState = STATE_PLAYBACK_COMPLETED;
        if (mOnCompletionListener != null) mOnCompletionListener!!.onCompletion(mp)
    }
    var mPreparedListener: OnPreparedListener = object : OnPreparedListener {
        override fun onPrepared(mp: MediaPlayer) {
            //必须是正常状态
            if (mCurrentState == STATE_PREPARING) {
                mCurrentState = STATE_PREPARED
                try {
                    duration = mp.duration
                } catch (e: IllegalStateException) {
                }
                try {
                    videoWidth = mp.videoWidth
                    videoHeight = mp.videoHeight
                } catch (e: IllegalStateException) {
                }
                when (mTargetState) {
                    STATE_PREPARED -> if (mOnPreparedListener != null) mOnPreparedListener!!.onPrepared(
                        mMediaPlayer
                    )
                    STATE_PLAYING -> start()
                }
            }
        }
    }
    var mVideoSizeChangedListener: OnVideoSizeChangedListener =
        object : OnVideoSizeChangedListener {
            override fun onVideoSizeChanged(
                mp: MediaPlayer,
                width: Int,
                height: Int
            ) {
                videoWidth = width
                videoHeight = height
                if (mOnVideoSizeChangedListener != null) mOnVideoSizeChangedListener!!.onVideoSizeChanged(
                    mp,
                    width,
                    height
                )
            }
        }
    var mInfoListener = OnInfoListener { mp, what, extra ->
        if (mOnInfoListener != null) mOnInfoListener!!.onInfo(mp, what, extra)
        false
    }
    private val mSeekCompleteListener = OnSeekCompleteListener { mp ->
        if (mOnSeekCompleteListener != null) mOnSeekCompleteListener!!.onSeekComplete(mp)
    }
    private val mErrorListener: OnErrorListener? =
        OnErrorListener { mp, framework_err, impl_err ->
            mCurrentState = STATE_ERROR
            //			mTargetState = STATE_ERROR;
            //FIX，可以考虑出错以后重新开始
            if (mOnErrorListener != null) mOnErrorListener!!.onError(mp, framework_err, impl_err)
            true
        }

    /** 是否可用  */
    val isPrepared: Boolean
        get() = mMediaPlayer != null && mCurrentState == STATE_PREPARED

    val isComplate: Boolean
        get() = mMediaPlayer != null && mCurrentState == STATE_PLAYBACK_COMPLETED

    /** 是否已经释放  */
    val isRelease: Boolean
        get() = mMediaPlayer == null || mCurrentState == STATE_IDLE || mCurrentState == STATE_ERROR || mCurrentState == STATE_RELEASED

    private val mVideoHandler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                HANDLER_MESSAGE_PARSE -> pause()
                HANDLER_MESSAGE_LOOP -> if (isPlaying) {
                    seekTo(msg.arg1)
                    sendMessageDelayed(
                        this.obtainMessage(
                            HANDLER_MESSAGE_LOOP,
                            msg.arg1,
                            msg.arg2
                        ), msg.arg2.toLong()
                    )
                }
                else -> {
                }
            }
            super.handleMessage(msg)
        }
    }

    /** 定时暂停  */
    fun pauseDelayed(delayMillis: Int) {
        if (mVideoHandler.hasMessages(HANDLER_MESSAGE_PARSE)) mVideoHandler.removeMessages(
            HANDLER_MESSAGE_PARSE
        )
        mVideoHandler.sendEmptyMessageDelayed(
            HANDLER_MESSAGE_PARSE,
            delayMillis.toLong()
        )
    }

    /** 暂停并且清除定时任务  */
    fun pauseClearDelayed() {
        pause()
        if (mVideoHandler.hasMessages(HANDLER_MESSAGE_PARSE)) mVideoHandler.removeMessages(
            HANDLER_MESSAGE_PARSE
        )
        if (mVideoHandler.hasMessages(HANDLER_MESSAGE_LOOP)) mVideoHandler.removeMessages(
            HANDLER_MESSAGE_LOOP
        )
    }

    /** 区域内循环播放  */
    fun loopDelayed(startTime: Int, endTime: Int) {
        if (mVideoHandler.hasMessages(HANDLER_MESSAGE_PARSE)) mVideoHandler.removeMessages(
            HANDLER_MESSAGE_PARSE
        )
        if (mVideoHandler.hasMessages(HANDLER_MESSAGE_LOOP)) mVideoHandler.removeMessages(
            HANDLER_MESSAGE_LOOP
        )
        val delayMillis = endTime - startTime
        seekTo(startTime)
        if (!isPlaying) start()
        if (mVideoHandler.hasMessages(HANDLER_MESSAGE_LOOP)) mVideoHandler.removeMessages(
            HANDLER_MESSAGE_LOOP
        )
        mVideoHandler.sendMessageDelayed(
            mVideoHandler.obtainMessage(
                HANDLER_MESSAGE_LOOP,
                currentPosition,
                delayMillis
            ), delayMillis.toLong()
        )
    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        val needReOpen = surfaceHolder == null
        surfaceHolder = holder
        if (needReOpen) {
            reOpen()
        }
    }

    override fun surfaceChanged(
        holder: SurfaceHolder,
        format: Int,
        width: Int,
        height: Int
    ) {
        surfaceHolder = holder
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        surfaceHolder = null
        release()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    companion object {
        /** 定时暂停  */
        private const val HANDLER_MESSAGE_PARSE = 0

        /** 定时循环  */
        private const val HANDLER_MESSAGE_LOOP = 1
        private const val STATE_ERROR = -1
        private const val STATE_IDLE = 0
        private const val STATE_PREPARING = 1
        private const val STATE_PREPARED = 2
        private const val STATE_PLAYING = 3
        private const val STATE_PAUSED = 4

        /**
         * PlaybackCompleted状态：文件正常播放完毕，而又没有设置循环播放的话就进入该状态，
         * 并会触发OnCompletionListener的onCompletion
         * ()方法。此时可以调用start()方法重新从头播放文件，也可以stop()停止MediaPlayer，或者也可以seekTo()来重新定位播放位置。
         */
        private const val STATE_PLAYBACK_COMPLETED = 5

        /** Released/End状态：通过release()方法可以进入End状态  */
        private const val STATE_RELEASED = 5

        /** 更新音量  */
        fun getSystemVolumn(context: Context?): Float {
            if (context != null) {
                try {
                    val mAudioManager =
                        context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
                    val maxVolumn = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
                    return mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC) * 1.0f / maxVolumn
                } catch (e: UnsupportedOperationException) {
                }
            }
            return 0.5f
        }
    }
}